#include "NRenderThread.h"
#include "NPlatform.h"
#include "NDevice.h"
#include "NeroCore\NMemoryManager.h"

extern bool GIsRendering;

using namespace Engine;

NRenderThread* GRenderThread = NULL;

RTTI_DEFINITIONS(NRenderThread)

void RenderThread_Main(void*)
{
#ifdef WIN_32
	Core::SetThreadName(DWORD(-1), "Render Thread");
#endif	
	NDevice::sMutex = CreateMutex(NULL,
	 				   FALSE,
					   NULL);

	if(!NDevice::sMutex)
	{
		return;
	}

	while(GIsRendering)
	{
		DWORD dwWaitResult; 
		dwWaitResult = WaitForSingleObject( NDevice::sMutex,    // handle to mutex
											INFINITE);  // no time-out interval

		switch (dwWaitResult) 
        {
			case WAIT_OBJECT_0: 
				__try
				{
					GetPlatform()->Render();
				}
				__finally
				{
					 // Release ownership of the mutex object
                    if (! ReleaseMutex(NDevice::sMutex)) 
                    { 
                        // Handle error.
                    } 
				}
				break;
			// The thread got ownership of an abandoned mutex
            // The database is in an indeterminate state
            case WAIT_ABANDONED: 
                break;
		}
	}
}

void StartRenderThread()
{
	GIsRendering = true;
	if(GRenderThread)
	{
		return;
	}

	GRenderThread = MY_NEW(Memory::HID_Rendering,"NRenderThread") NRenderThread();

	GRenderThread->Run();
}

void StopRenderThread()
{
	GIsRendering = false;

	if(GRenderThread)
	{
		CloseHandle(GRenderThread->GetHandle());
		delete GRenderThread;
		GRenderThread = NULL;
	}
}

NRenderThread::NRenderThread(void)
{
}

NRenderThread::~NRenderThread(void)
{
}

HANDLE NRenderThread::GetHandle()
{
	return mThreadHandle;

}

void NRenderThread::Run()
{
#ifdef WIN32
	mThreadHandle = CreateThread( NULL,       // default security attributes
								  0,          // default stack size
								  (LPTHREAD_START_ROUTINE) RenderThread_Main, 
								  NULL,       // no thread function arguments
								  0,          // default creation flags
								  &mThreadID); // receive thread identifier
	if(!mThreadHandle)
	{
		return;
	}
#endif
}